import 'dart:async';

import 'package:bottom_picker/bottom_picker.dart';
import 'package:concierge/app/common/app_theme.dart';
import 'package:concierge/app/widgets/ms_svg_icon.dart';
import 'package:concierge/generated/locales.g.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_picker_plus/picker.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:get/get_navigation/src/dialog/dialog_route.dart';

class Modal {
  static void bottomSheet({
    String title = '',
    String content = '',
    List<ModalBottomSheetButton> buttons = const [],
    bool closable = false,
    List<String>? description,
    Color? barrierColor = Colors.black54,
    String? textConfirm,
    String? textCancel,
    VoidCallback? onConfirm,
    VoidCallback? onCancel,
    Widget? child,
  }) {
    final colorScheme = Get.context!.theme.colorScheme;

    Get.bottomSheet(
      ModalBottomSheet(
        title: title,
        content: content,
        closable: closable,
        buttons: buttons,
        description: description ?? [],
        textConfirm: textConfirm,
        onConfirm: onConfirm,
        textCancel: textCancel,
        onCancel: onCancel,
        child: child,
      ),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(AppTheme.cornerLarge.w),
          topRight: Radius.circular(AppTheme.cornerLarge.w),
        ),
      ),
      backgroundColor: colorScheme.primaryContainer,
      barrierColor: barrierColor,
    );
  }

  static void customBottomSheet({
    Widget? child,
    Color? barrierColor = Colors.black54,
    bool indicatorAtTop = true,
  }) {
    final colorScheme = Get.context!.theme.colorScheme;

    Get.bottomSheet(
      isScrollControlled: true,
      ModalCustomBottomSheet(child: child, indicatorAtTop: indicatorAtTop),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(AppTheme.cornerLarge.w),
          topRight: Radius.circular(AppTheme.cornerLarge.w),
        ),
      ),
      backgroundColor: colorScheme.primaryContainer,
      barrierColor: barrierColor,
    );
  }

  static Future<void> dialog({
    required String title,
    String? content,
    Color barrierColor = Colors.black54,
    bool barrierDismissible = false,
    TextAlign contentAlign = TextAlign.left,
    Widget? customContent,
    PopInvokedWithResultCallback? onWillPop,
    String? textConfirm,
    String? textCancel,
    VoidCallback? onConfirm,
    VoidCallback? onCancel,
    ButtonStyle? confirmStyle,
    bool autoClose = true,
    bool canPop = false,
    bool danger = false,
  }) {
    Widget baseDialog = PopScope(
      canPop: canPop,
      onPopInvokedWithResult: (didPop, result) {
        onWillPop?.call(didPop, result);
      },
      child: ModalDialog(
        title: title,
        content: content,
        contentAlign: contentAlign,
        customContent: customContent,
        textConfirm: textConfirm,
        textCancel: textCancel,
        onConfirm: onConfirm,
        autoClose: autoClose,
        onCancel: onCancel,
        confirmStyle: confirmStyle,
        danger: danger,
      ),
    );

    return Get.dialog(
      baseDialog,
      barrierColor: barrierColor,
      barrierDismissible: barrierDismissible,
    );
  }

  static VoidCallback loading({
    String title = '',
    Color barrierColor = Colors.black54,
    bool barrierDismissible = false,
    bool canPop = true,
    PopInvokedWithResultCallback? onWillPop,
    Alignment alignment = Alignment.center,
    VoidCallback? onClose,
    Axis axis = Axis.horizontal,
  }) {
    if (Get.context == null) {
      return () {};
    }

    final size = (title.isNotEmpty && axis == Axis.horizontal) ? 16.w : 24.w;
    return toast(
      title: title,
      barrierColor: barrierColor,
      barrierDismissible: barrierDismissible,
      canPop: canPop,
      onWillPop: onWillPop,
      onClose: onClose,
      alignment: alignment,
      icon: SizedBox(
        width: size,
        height: size,
        child: CircularProgressIndicator(strokeWidth: 2.w),
      ),
      padding: title.isEmpty
          ? EdgeInsets.all(16.w)
          : EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.w),
      duration: 0.seconds,
      axis: axis,
    );
  }

  static VoidCallback toast({
    required String title,
    Color barrierColor = Colors.black54,
    bool barrierDismissible = false,
    bool canPop = true,
    PopInvokedWithResultCallback? onWillPop,
    Duration duration = const Duration(seconds: 1, milliseconds: 500),
    Widget? icon,
    Alignment alignment = Alignment.center,
    VoidCallback? onClose,
    Axis axis = Axis.horizontal,
    EdgeInsetsGeometry? padding,
  }) {
    if (Get.context == null || Get.overlayContext == null) {
      return () {};
    }

    bool isClosed = false;
    Widget baseToast = PopScope(
      canPop: canPop,
      onPopInvokedWithResult: (didPop, result) {
        if (didPop) {
          isClosed = true;
          onClose?.call();
        }
        onWillPop?.call(didPop, result);
      },
      child: ModalToast(
        title: title,
        icon: icon,
        alignment: alignment,
        axis: axis,
        padding: padding,
      ),
    );

    final toast = _generalDialog(
      baseToast,
      barrierColor: barrierColor,
      barrierDismissible: barrierDismissible,
    );

    if (Get.overlayContext == null) {
      return () {};
    }

    final nav = Navigator.of(Get.overlayContext!, rootNavigator: true);

    if (nav.mounted == false) {
      return () {};
    }

    try {
      nav.push(toast);
    } catch (e) {
      return () {};
    }

    void remove() {
      if (!isClosed) {
        onClose?.call();
        try {
          nav.removeRoute(toast);
        } catch (e) {
          // 忽略移除路由时的错误
        }
      }
      isClosed = true;
    }

    if (duration > const Duration(seconds: 0, milliseconds: 0)) {
      Future.delayed(duration).then((_) {
        remove();
      });
    }

    return remove;
  }

  static showEditDialog(
    String title,
    String name,
    int maxLength,
    void Function(String) onNameChanged, [
    TextInputType? keyboardType,
  ]) {
    //logger.d('keyboardType: $keyboardType');
    var textTheme = Get.context!.textTheme;
    var colorScheme = Get.context!.theme.colorScheme;
    TextEditingController nameEditingController = TextEditingController(
      text: name,
    );
    Modal.dialog(
      title: title,
      autoClose: false,
      customContent: Material(
        color: Colors.transparent,
        child: Padding(
          padding: EdgeInsets.only(bottom: 10.h),
          child: TextField(
            controller: nameEditingController,
            maxLength: maxLength == 0 ? null : maxLength,
            textInputAction: TextInputAction.done,
            keyboardType: keyboardType ?? TextInputType.text,
            /*inputFormatters: [
              FilteringTextInputFormatter(
                RegExp('^[a-zA-Z0-9]+'),
                allow: true,
              ),
            ],*/
            style: textTheme.titleMedium?.copyWith(color: colorScheme.primary),
            decoration: InputDecoration(
              contentPadding: EdgeInsets.symmetric(
                vertical: 16.h,
                horizontal: 10.w,
              ),
              counterText: '',
              hintText: '',
              border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(AppTheme.cornerMedium.w),
                borderSide: BorderSide(color: colorScheme.outline, width: 2.w),
              ),
              focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(AppTheme.cornerMedium.w),
                borderSide: BorderSide(
                  color: colorScheme.primaryFixed,
                  width: 2.w,
                ),
              ),
            ),
          ),
        ),
      ),
      content: maxLength == 0
          ? null
          : LocaleKeys.maximum_of_max_length_characters.trParams({
              "maxLength": maxLength.toString(),
            }),
      textCancel: LocaleKeys.cancel.tr,
      textConfirm: LocaleKeys.confirm.tr,
      onConfirm: () {
        if (nameEditingController.text.isEmpty) {
          return;
        }
        if (nameEditingController.text != name) {
          onNameChanged(nameEditingController.text);
        }
        Get.back();
      },
    );
  }

  static showBirthdayPicker(
    BuildContext context,
    String? birthday,
    void Function(DateTime birthday) onChose,
  ) {
    var now = DateTime.now();
    DateTime date = birthday == null || birthday.isEmpty || birthday == "-"
        ? DateTime(now.year - 1, now.month, now.day)
        : DateTime.parse(birthday);
    BottomPicker.date(
      pickerTitle: Text(
        LocaleKeys.birth_date.tr,
        style: TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 15,
          color: context.theme.colorScheme.primary,
        ),
      ),
      dateOrder: DatePickerDateOrder.ymd,
      initialDateTime: DateTime(date.year, date.month, date.day),
      maxDateTime: DateTime(now.year - 1, 12, 31),
      minDateTime: DateTime(1900),
      pickerTextStyle: TextStyle(
        color: context.theme.colorScheme.primary,
        fontWeight: FontWeight.bold,
        fontSize: 22,
      ),
      onChange: (index) {},
      onSubmit: (index) {
        onChose.call(index);
      },
      backgroundColor: context.theme.colorScheme.primaryContainer,
      buttonContent: Center(
        child: FittedBox(
          fit: BoxFit.scaleDown,
          child: Text(LocaleKeys.confirm.tr),
        ),
      ),
      closeIconColor: context.theme.colorScheme.onPrimary,
      buttonSingleColor: context.theme.colorScheme.secondaryContainer,
      dismissable: true,
    ).show(context);
  }

  static showGenderPicker(
    BuildContext context,
    int gender,
    void Function(int result) onChose,
  ) {
    var list = [LocaleKeys.male.tr, LocaleKeys.female.tr];
    final picker = BottomPicker(
      items: list.map((it) => Center(child: Text(it))).toList(),
      selectedItemIndex: gender == 1 ? 0 : 1,
      pickerTitle: Text(
        LocaleKeys.gender.tr,
        style: TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 15,
          color: context.theme.colorScheme.primary,
        ),
      ),
      titleAlignment: Alignment.center,
      pickerTextStyle: TextStyle(
        color: context.theme.colorScheme.primary,
        fontWeight: FontWeight.bold,
        fontSize: 22,
      ),
      backgroundColor: context.theme.colorScheme.primaryContainer,
      buttonContent: Center(
        child: FittedBox(
          fit: BoxFit.scaleDown,
          child: Text(LocaleKeys.confirm.tr),
        ),
      ),
      closeIconColor: context.theme.colorScheme.onPrimary,
      buttonSingleColor: context.theme.colorScheme.secondaryContainer,
      dismissable: true,
      onSubmit: (index) {
        //logger.d('picker: $index');
        if (index == 0) {
          onChose.call(1);
        } else if (index == 1) {
          onChose.call(2);
        }
      },
    ).show(context);
  }

  static showHeightPicker(
    BuildContext context,
    int height,
    void Function(int result) onChose,
  ) {
    List<int> numberList = List<int>.generate(
      300 - 50 + 1,
      (index) => index + 50,
    );
    var selectedItemIndex = numberList.indexOf(height);
    if (selectedItemIndex < 0) {
      selectedItemIndex = numberList.indexOf(170);
    }
    BottomPicker(
      items: numberList.map((it) => Center(child: Text('${it}CM'))).toList(),
      selectedItemIndex: selectedItemIndex,
      pickerTitle: Text(
        LocaleKeys.height.tr,
        style: TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 15,
          color: context.theme.colorScheme.primary,
        ),
      ),
      titleAlignment: Alignment.center,
      pickerTextStyle: TextStyle(
        color: context.theme.colorScheme.primary,
        fontWeight: FontWeight.bold,
        fontSize: 22,
      ),
      backgroundColor: context.theme.colorScheme.primaryContainer,
      buttonContent: Center(
        child: FittedBox(
          fit: BoxFit.scaleDown,
          child: Text(LocaleKeys.confirm.tr),
        ),
      ),
      closeIconColor: context.theme.colorScheme.onPrimary,
      buttonSingleColor: context.theme.colorScheme.secondaryContainer,
      dismissable: true,
      onSubmit: (index) {
        onChose.call(numberList[index]);
      },
    ).show(context);
  }

  static showWeightPicker(
    BuildContext context,
    int weight,
    void Function(int result) onChose,
  ) {
    List<int> numberList = List<int>.generate(
      300 - 30 + 1,
      (index) => index + 30,
    );
    var selectedItemIndex = numberList.indexOf(weight);
    if (selectedItemIndex < 0) {
      selectedItemIndex = numberList.indexOf(100);
    }
    BottomPicker(
      items: numberList.map((it) => Center(child: Text('${it}KG'))).toList(),
      selectedItemIndex: selectedItemIndex,
      pickerTitle: Text(
        LocaleKeys.weight.tr,
        style: TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 15,
          color: context.theme.colorScheme.primary,
        ),
      ),
      titleAlignment: Alignment.center,
      pickerTextStyle: TextStyle(
        color: context.theme.colorScheme.primary,
        fontWeight: FontWeight.bold,
        fontSize: 22,
      ),
      backgroundColor: context.theme.colorScheme.primaryContainer,
      buttonContent: Center(
        child: FittedBox(
          fit: BoxFit.scaleDown,
          child: Text(LocaleKeys.confirm.tr),
        ),
      ),
      closeIconColor: context.theme.colorScheme.onPrimary,
      buttonSingleColor: context.theme.colorScheme.secondaryContainer,
      dismissable: true,
      onSubmit: (index) {
        onChose.call(numberList[index]);
      },
    ).show(context);
  }

  static showHeightAndWeightPicker(
    BuildContext context, {
    required int weight,
    required int height,
    void Function(int height, int weight)? onConfirm,
  }) {
    final colorScheme = context.theme.colorScheme;
    final textTheme = context.textTheme;
    final hColumn = const NumberPickerColumn(
      begin: 50,
      end: 300,
      suffix: Text('CM'),
    );

    final wColumn = const NumberPickerColumn(
      begin: 30,
      end: 300,
      suffix: Text('KG'),
    );
    final hSelected = height > hColumn.begin ? height - hColumn.begin : 0;
    final wSelected = weight > wColumn.begin ? weight - wColumn.begin : 0;
    Picker(
      selecteds: [hSelected, wSelected],
      adapter: NumberPickerAdapter(data: [hColumn, wColumn]),
      backgroundColor: colorScheme.primaryContainer,
      containerColor: colorScheme.primaryContainer,
      cancelText: LocaleKeys.cancel.tr,
      confirmText: LocaleKeys.confirm.tr,
      cancelTextStyle: textTheme.titleMedium?.copyWith(
        color: colorScheme.onPrimary,
      ),
      confirmTextStyle: textTheme.titleMedium?.copyWith(
        color: colorScheme.primaryFixed,
      ),
      headerDecoration: BoxDecoration(
        color: colorScheme.primaryContainer,
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(AppTheme.cornerLarge.w),
          topRight: Radius.circular(AppTheme.cornerLarge.w),
        ),
      ),
      height: 300.h,
      itemExtent: 44.h,
      selectionOverlay: Container(
        decoration: BoxDecoration(
          color: colorScheme.secondaryContainer,
          borderRadius: BorderRadius.circular(AppTheme.cornerXSmall.w),
        ),
        margin: EdgeInsets.symmetric(horizontal: 20.w),
      ),
      title: Text(
        LocaleKeys.height_and_weight.tr,
        style: textTheme.headlineSmall?.copyWith(color: colorScheme.onPrimary),
      ),
      textStyle: textTheme.displayMedium?.copyWith(color: colorScheme.primary),
      onConfirm: (Picker picker, List<int> value) {
        final values = picker.getSelectedValues();
        onConfirm?.call(values.first, values.last);
        //logger.i('${values.first}, ${values.last}');
      },
    ).showModal(context);
  }

  static OverlayEntry? _currentSyncSnackbar;

  static void syncSnackbar({
    String? title,
    SyncDataStatus status = SyncDataStatus.pending,
    Duration duration = const Duration(seconds: 5),
  }) {
    // 移除之前的 snackbar
    _currentSyncSnackbar?.remove();

    final colorScheme = Get.theme.colorScheme;
    final textTheme = Get.textTheme;
    String t = title ?? LocaleKeys.syncing_data.tr;
    Color backgroundColor = colorScheme.primaryFixed;

    if (status == SyncDataStatus.finish) {
      t = LocaleKeys.data_sync_completed.tr;
      backgroundColor = colorScheme.secondaryFixed;
    }

    if (status == SyncDataStatus.fail) {
      t = LocaleKeys.data_sync_failed.tr;
      backgroundColor = colorScheme.error;
    }

    _currentSyncSnackbar = OverlayEntry(
      builder: (context) => _CustomSyncSnackbar(
        message: t,
        backgroundColor: backgroundColor,
        textStyle: textTheme.titleSmall?.copyWith(color: Colors.white),
        duration: duration,
        onDismiss: () {
          _currentSyncSnackbar?.remove();
          _currentSyncSnackbar = null;
        },
      ),
    );

    Overlay.of(Get.context!).insert(_currentSyncSnackbar!);
  }
}

enum SyncDataStatus { pending, finish, fail, cancelled }

class _CustomSyncSnackbar extends StatefulWidget {
  final String message;
  final Color backgroundColor;
  final TextStyle? textStyle;
  final Duration duration;
  final VoidCallback onDismiss;

  const _CustomSyncSnackbar({
    required this.message,
    required this.backgroundColor,
    this.textStyle,
    required this.duration,
    required this.onDismiss,
  });

  @override
  State<_CustomSyncSnackbar> createState() => _CustomSyncSnackbarState();
}

class _CustomSyncSnackbarState extends State<_CustomSyncSnackbar>
    with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<Offset> _slideAnimation;
  Timer? _dismissTimer;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      duration: const Duration(milliseconds: 300),
      vsync: this,
    );
    _slideAnimation =
        Tween<Offset>(begin: const Offset(0, -1), end: Offset.zero).animate(
          CurvedAnimation(parent: _animationController, curve: Curves.easeOut),
        );

    _animationController.forward();

    _dismissTimer = Timer(widget.duration, () {
      _dismiss();
    });
  }

  @override
  void dispose() {
    _dismissTimer?.cancel();
    _animationController.dispose();
    super.dispose();
  }

  void _dismiss() async {
    await _animationController.reverse();
    widget.onDismiss();
  }

  @override
  Widget build(BuildContext context) {
    return Positioned(
      top: MediaQuery.of(context).padding.top + 10.w,
      left: 50.w,
      right: 50.w,
      child: SlideTransition(
        position: _slideAnimation,
        child: Material(
          color: Colors.transparent,
          child: Container(
            padding: EdgeInsets.all(8.w),
            decoration: BoxDecoration(
              color: widget.backgroundColor,
              borderRadius: BorderRadius.circular(AppTheme.cornerSmall.w),
            ),
            child: Center(child: Text(widget.message, style: widget.textStyle)),
          ),
        ),
      ),
    );
  }
}

class ModalDialog extends StatelessWidget {
  const ModalDialog({
    super.key,
    required this.title,
    this.content,
    this.contentAlign = TextAlign.left,
    this.customContent,
    this.textConfirm,
    this.textCancel,
    this.onConfirm,
    this.autoClose = true,
    this.onCancel,
    this.confirmStyle,
    this.danger = false,
  });

  final String title;
  final String? content;
  final TextAlign contentAlign;
  final Widget? customContent;
  final String? textConfirm;
  final String? textCancel;
  final VoidCallback? onConfirm;
  final bool autoClose;
  final VoidCallback? onCancel;
  final ButtonStyle? confirmStyle;
  final bool danger;

  Future<void> _onCancel() async {
    Get.back();
    await Future.delayed(Get.defaultDialogTransitionDuration);
    onCancel?.call();
  }

  Future<void> _onConfirm() async {
    if (autoClose) {
      Get.back();
      await Future.delayed(Get.defaultDialogTransitionDuration);
    }
    onConfirm?.call();
  }

  @override
  Widget build(BuildContext context) {
    final colorScheme = context.theme.colorScheme;
    final textTheme = context.theme.textTheme;
    final contentText = content != null
        ? Text(
            content!,
            textAlign: contentAlign,
            style: textTheme.bodySmall?.copyWith(color: colorScheme.tertiary),
          )
        : const SizedBox();

    List<Widget> baseContent = [customContent ?? const SizedBox(), contentText];

    List<Widget> actions = [];

    if (textCancel != null) {
      actions.add(
        Expanded(
          child: ElevatedButton(
            onPressed: () {
              _onCancel();
            },
            style: ElevatedButton.styleFrom(
              foregroundColor: colorScheme.onPrimary,
            ),
            child: FittedBox(
              fit: BoxFit.scaleDown,
              child: Text(
                textCancel!,
                textAlign: TextAlign.center,
                maxLines: 1,
                // 当文本溢出时，使用自动缩放处理
                overflow: TextOverflow.fade,
                softWrap: true,
                textScaler: TextScaler.linear(1.0),
              ),
            ),
          ),
        ),
      );
      if (textConfirm != null) {
        actions.add(SizedBox(width: AppTheme.cornerLarge.w));
      }
    }

    if (textConfirm != null) {
      Widget confirm = FilledButton(
        onPressed: () {
          _onConfirm();
        },
        style:
            confirmStyle ??
            (danger
                ? FilledButton.styleFrom(
                    backgroundColor: colorScheme.error,
                    foregroundColor: colorScheme.primary,
                  )
                : null),
        child: FittedBox(
          fit: BoxFit.scaleDown,
          child: Text(
            textConfirm!,
            textAlign: TextAlign.center,
            maxLines: 1,
            // 当文本溢出时，使用自动缩放处理
            overflow: TextOverflow.fade,
            softWrap: true,
            textScaler: TextScaler.linear(1.0),
          ),
        ),
      );
      actions.add(
        textCancel != null
            ? Expanded(child: confirm)
            : SizedBox(width: 125.w, child: confirm),
      );
    }

    final baseActions = actions.isNotEmpty
        ? Container(
            margin: EdgeInsets.only(top: (AppTheme.cornerLarge * 2).w),
            height: 36.h,
            child: Row(
              mainAxisAlignment: textCancel != null
                  ? MainAxisAlignment.spaceBetween
                  : MainAxisAlignment.center,
              children: actions,
            ),
          )
        : const SizedBox();

    return Center(
      child: Padding(
        padding: EdgeInsets.symmetric(horizontal: 28.w),
        child: Container(
          padding: EdgeInsets.all(AppTheme.cornerLarge.w),
          decoration: BoxDecoration(
            color: colorScheme.primaryContainer,
            borderRadius: BorderRadius.all(
              Radius.circular(AppTheme.cornerLarge.w),
            ),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Text(
                title,
                textAlign: TextAlign.center,
                style: textTheme.headlineSmall?.copyWith(
                  color: colorScheme.primary,
                ),
              ),
              SizedBox(
                height: (customContent != null || content != null)
                    ? AppTheme.cornerSmall
                    : 0,
              ),
              ...baseContent,
              baseActions,
            ],
          ),
        ),
      ),
    );
  }
}

class ModalToast extends StatelessWidget {
  const ModalToast({
    super.key,
    required this.title,
    this.icon,
    this.alignment = Alignment.center,
    this.axis = Axis.horizontal,
    this.padding,
  });

  final String title;
  final Widget? icon;
  final Alignment alignment;
  final Axis axis;
  final EdgeInsetsGeometry? padding;

  @override
  Widget build(BuildContext context) {
    double maxWidth = context.width * 0.85;

    final colorScheme = context.theme.colorScheme;
    final textTheme = context.theme.textTheme;

    List<Widget> iconWidget = [];
    if (icon != null) {
      iconWidget.addAll([
        IconTheme(
          data: IconThemeData(size: 24.w, color: colorScheme.primary),
          child: icon!,
        ),
        (title.isEmpty)
            ? const SizedBox()
            : SizedBox(height: 10.w, width: 10.w),
      ]);
    }

    List<Widget> children = [
      ...iconWidget,
      title.isEmpty
          ? const SizedBox()
          : Flexible(
              child: Text(
                title,
                textAlign: TextAlign.center,
                style: textTheme.headlineSmall?.copyWith(
                  color: colorScheme.primary,
                ),
              ),
            ),
    ];

    return Align(
      alignment: alignment,
      child: Container(
        decoration: BoxDecoration(
          color: colorScheme.primaryContainer,
          borderRadius: BorderRadius.all(
            Radius.circular(AppTheme.cornerSmall.w),
          ),
        ),
        padding:
            padding ?? EdgeInsets.symmetric(vertical: 6.w, horizontal: 12.w),
        constraints: BoxConstraints(maxWidth: maxWidth),
        child: axis == Axis.horizontal
            ? Row(mainAxisSize: MainAxisSize.min, children: children)
            : Column(mainAxisSize: MainAxisSize.min, children: children),
      ),
    );
  }
}

GetDialogRoute _generalDialog(
  Widget widget, {
  bool barrierDismissible = true,
  Color? barrierColor,
  bool useSafeArea = true,
  Duration? transitionDuration,
  Curve? transitionCurve,
}) {
  if (Get.context == null) {
    return GetDialogRoute(
      pageBuilder: (context, animation, secondaryAnimation) => widget,
      barrierDismissible: barrierDismissible,
      barrierLabel: 'Dismiss',
      barrierColor: barrierColor ?? Colors.black54,
      transitionDuration:
          transitionDuration ?? const Duration(milliseconds: 300),
      transitionBuilder: (context, animation, secondaryAnimation, child) {
        return FadeTransition(
          opacity: CurvedAnimation(
            parent: animation,
            curve: transitionCurve ?? Curves.easeInOut,
          ),
          child: child,
        );
      },
    );
  }

  final theme = Theme.of(Get.context!);
  return GetDialogRoute(
    pageBuilder: (context, animation, secondaryAnimation) {
      final pageChild = widget;
      Widget dialog = Builder(
        builder: (context) {
          return Theme(data: theme, child: pageChild);
        },
      );
      if (useSafeArea) {
        dialog = SafeArea(child: dialog);
      }
      return dialog;
    },
    barrierDismissible: barrierDismissible,
    barrierLabel: MaterialLocalizations.of(
      Get.context!,
    ).modalBarrierDismissLabel,
    barrierColor: barrierColor ?? Colors.black54,
    transitionDuration:
        transitionDuration ?? Get.defaultDialogTransitionDuration,
    transitionBuilder: (context, animation, secondaryAnimation, child) {
      return FadeTransition(
        opacity: CurvedAnimation(
          parent: animation,
          curve: transitionCurve ?? Get.defaultDialogTransitionCurve,
        ),
        child: child,
      );
    },
  );
}

class ModalBottomSheetButton {
  final Widget? icon;
  final String text;
  final VoidCallback? onPressed;
  final bool danger;
  final MainAxisAlignment mainAxisAlignment;

  const ModalBottomSheetButton({
    this.icon,
    required this.text,
    this.onPressed,
    this.danger = false,
    this.mainAxisAlignment = MainAxisAlignment.start,
  });
}

class ModalBottomSheet extends StatelessWidget {
  const ModalBottomSheet({
    super.key,
    this.title = '',
    this.content = '',
    this.buttons = const [],
    this.description = const [],
    this.textConfirm,
    this.textCancel,
    this.onConfirm,
    this.onCancel,
    this.closable = false,
    this.child,
  });

  final String title;
  final String content;
  final List<ModalBottomSheetButton> buttons;
  final List<String> description;
  final String? textConfirm;
  final String? textCancel;
  final VoidCallback? onConfirm;
  final VoidCallback? onCancel;
  final bool closable;
  final Widget? child;
  Future<void> _onCancel() async {
    Get.back();
    await Future.delayed(Get.defaultDialogTransitionDuration);
    onCancel?.call();
  }

  @override
  Widget build(BuildContext context) {
    final colorScheme = context.theme.colorScheme;
    final textTheme = context.textTheme;

    Widget titleWidget = const SizedBox();

    if (!closable) {
      titleWidget = Center(
        child: Container(
          width: 64.w,
          height: 6.h,
          margin: EdgeInsets.only(bottom: 20.h),
          decoration: BoxDecoration(
            color: colorScheme.outline,
            borderRadius: BorderRadius.all(
              Radius.circular(AppTheme.cornerLarge.w),
            ),
          ),
        ),
      );
    }

    Widget buttonsWidget = const SizedBox();
    if (buttons.isNotEmpty) {
      buttonsWidget = Padding(
        padding: EdgeInsets.only(top: 20.h),
        child: ListView.separated(
          shrinkWrap: true,
          physics: NeverScrollableScrollPhysics(),
          padding: EdgeInsets.zero,
          itemBuilder: (context, index) {
            final button = buttons[index];
            final color = button.danger
                ? colorScheme.error
                : colorScheme.primary;
            return InkWell(
              onTap: () async {
                await _onCancel();
                button.onPressed?.call();
              },
              borderRadius: BorderRadius.circular(AppTheme.cornerMedium.w),
              child: Container(
                height: 56.h,
                padding: EdgeInsets.all(16.w),
                decoration: BoxDecoration(
                  color: colorScheme.secondaryContainer,
                  borderRadius: BorderRadius.circular(AppTheme.cornerMedium.w),
                ),
                child: IconTheme(
                  data: IconThemeData(color: color, size: 24.w),
                  child: Row(
                    mainAxisAlignment: button.mainAxisAlignment,
                    children: [
                      button.icon ?? const SizedBox(),
                      SizedBox(width: button.icon != null ? 8.w : 0),
                      Text(
                        button.text,
                        style: textTheme.titleMedium?.copyWith(color: color),
                      ),
                    ],
                  ),
                ),
              ),
            );
          },
          separatorBuilder: (context, index) => SizedBox(height: 16.h),
          itemCount: buttons.length,
        ),
      );
    }

    Widget descriptions = const SizedBox();
    if (description.isNotEmpty) {
      Widget descriptionsList = ListView.separated(
        physics: NeverScrollableScrollPhysics(),
        shrinkWrap: true,
        padding: EdgeInsets.zero,
        itemBuilder: (context, index) => Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
              margin: EdgeInsets.only(left: 8.w, right: 8.w, top: 8.h),
              width: 6.w,
              height: 6.w,
              decoration: BoxDecoration(
                color: colorScheme.tertiary,
                borderRadius: BorderRadius.all(
                  Radius.circular(AppTheme.cornerSmall.w),
                ),
              ),
            ),
            Expanded(
              child: Text(
                description[index],
                style: textTheme.bodyMedium?.copyWith(
                  color: colorScheme.tertiary,
                ),
              ),
            ),
          ],
        ),
        separatorBuilder: (context, index) => SizedBox(height: 10.w),
        itemCount: description.length,
      );
      descriptions = Container(
        height: 300.h,
        child: SingleChildScrollView(child: descriptionsList),
      );
    }
    List<Widget> actions = [];

    if (textCancel != null) {
      actions.add(
        SizedBox(
          width: 125.w,
          height: 36.h,
          child: ElevatedButton(
            onPressed: () {
              _onCancel();
            },
            style: ElevatedButton.styleFrom(
              foregroundColor: colorScheme.onPrimary,
            ),
            child: Text(textCancel!),
          ),
        ),
      );
    }

    if (textConfirm != null) {
      actions.add(
        SizedBox(
          width: 125.w,
          height: 36.h,
          child: FilledButton(
            onPressed: () {
              if (onConfirm == null) {
                Get.back();
              } else {
                onConfirm?.call();
              }
            },
            child: Text(textConfirm!),
          ),
        ),
      );
    }

    Widget baseActions = const SizedBox();
    if (actions.isNotEmpty) {
      baseActions = Container(
        padding: EdgeInsets.only(bottom: 16.h, top: 40.h),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: actions,
        ),
      );
    }

    return SafeArea(
      child: Padding(
        padding: EdgeInsets.all(16.w),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            titleWidget,
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text(
                  title,
                  style: textTheme.headlineMedium?.copyWith(
                    color: colorScheme.primary,
                  ),
                ),
                closable
                    ? GestureDetector(
                        onTap: () {
                          _onCancel();
                        },
                        child: MSSvgIcon('close', size: 24.w),
                      )
                    : const SizedBox(),
              ],
            ),
            content.isNotEmpty
                ? Padding(
                    padding: EdgeInsets.symmetric(vertical: 10.w),
                    child: Text(content, style: textTheme.headlineSmall),
                  )
                : const SizedBox(),
            child ?? const SizedBox(),
            buttonsWidget,
            descriptions,
            baseActions,
          ],
        ),
      ),
    );
  }
}

class ModalCustomBottomSheet extends StatelessWidget {
  const ModalCustomBottomSheet({
    super.key,
    this.child,
    this.indicatorAtTop = true,
  });

  final Widget? child;
  final bool indicatorAtTop;

  @override
  Widget build(BuildContext context) {
    final colorScheme = context.theme.colorScheme;

    Widget titleWidget = Center(
      child: Container(
        width: 64.w,
        height: 6.h,
        margin: EdgeInsets.only(
          bottom: indicatorAtTop ? 20.h : 0,
          top: indicatorAtTop ? 0 : 20.h,
        ),
        decoration: BoxDecoration(
          color: colorScheme.outline,
          borderRadius: BorderRadius.all(
            Radius.circular(AppTheme.cornerLarge.w),
          ),
        ),
      ),
    );

    Widget childWidget = const SizedBox();
    if (child != null) {
      childWidget = child!;
    }

    return SafeArea(
      child: Padding(
        padding: EdgeInsets.all(16.w),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: indicatorAtTop
              ? [titleWidget, childWidget]
              : [childWidget, titleWidget],
        ),
      ),
    );
  }
}
